package org.dromara.common.sse.controller

import cn.dev33.satoken.annotation.SaIgnore
import cn.dev33.satoken.stp.StpUtil
import org.dromara.common.core.domain.R
import org.dromara.common.core.domain.R.Companion.ok
import org.dromara.common.satoken.utils.LoginHelper.getUserId
import org.dromara.common.sse.core.SseEmitterManager
import org.springframework.beans.factory.DisposableBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.http.MediaType
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter

/**
 * SSE 控制器
 *
 * @author LikeYouDo
 */
@RestController
@ConditionalOnProperty(value = ["sse.enabled"], havingValue = "true")
class SseController(
    private val sseEmitterManager: SseEmitterManager
): DisposableBean {
    /**
     * 建立 SSE 连接
     */
    @GetMapping(value = [$$"${sse.path}"], produces = [MediaType.TEXT_EVENT_STREAM_VALUE])
    fun connect(): SseEmitter? {
        if (!StpUtil.isLogin()) {
            return null
        }
        val tokenValue = StpUtil.getTokenValue()
        val userId = getUserId()
        return sseEmitterManager.connect(userId!!, tokenValue)
    }

    /**
     * 关闭 SSE 连接
     */
    @SaIgnore
    @GetMapping(value = [$$"${sse.path}/close"])
    fun close(): R<Void?> {
        val tokenValue = StpUtil.getTokenValue()
        val userId = getUserId()
        sseEmitterManager.disconnect(userId, tokenValue)
        return ok<Void?>()
    }

    // 以下为demo仅供参考 禁止使用 请在业务逻辑中使用工具发送而不是用接口发送
    // /**
    //  * 向特定用户发送消息
    //  *
    //  * @param userId 目标用户的 ID
    //  * @param msg    要发送的消息内容
    //  */
    // @GetMapping(value = ["\${sse.path}/send"])
    // fun send(userId: Long, msg: String): R<Void?> {
    //     val dto = SseMessageDto()
    //     dto.userIds = listOf(userId)
    //     dto.message = msg
    //     sseEmitterManager.publishMessage(dto)
    //     return ok<Void?>()
    // }
    //
    // /**
    //  * 向所有用户发送消息
    //  *
    //  * @param msg 要发送的消息内容
    //  */
    // @GetMapping(value = ["\${sse.path}/sendAll"])
    // fun send(msg: String): R<Void?> {
    //     sseEmitterManager.publishAll(msg)
    //     return ok<Void?>()
    // }

    /**
     * 清理资源。此方法目前不执行任何操作，但避免因未实现而导致错误
     */
    @Throws(Exception::class)
    override fun destroy() {
        // 销毁时不需要做什么 此方法避免无用操作报错
    }
}
